package com.imdroid.carac.audioCodec;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

import android.media.AudioFormat;
import android.media.AudioRecord;
import android.media.MediaRecorder;

public class UDPMicrophone {
	private static ExecutorService service;
	private static Future<Void> recordTask;
	private static StreamListener streamListener;
	private static AudioRecord recorder;
	private volatile static boolean stop = false;

	public static boolean isRecordingStarted() {
		return false;
	}

	public static void startRecording(StreamListener listener) {
		if (streamListener != null && streamListener != listener) {
			throw new RuntimeException(
					"Previous recording not stopped or not stopped correctly, old stream listener not released.");
		}

		if (streamListener != null) {
			// already started
			return;
		}

		streamListener = listener;
		UDPSpeaker.pause();
		stop = false;
		service = Executors.newFixedThreadPool(1);
		recordTask = service.submit(new Callable<Void>() {
			@Override
			public Void call() throws Exception {
				C.encReset();
				byte[] buffer = new byte[C.encPcmBytes];
				int bufP = 0;

				int bufSize = AudioRecord.getMinBufferSize(C.samplesPerSec,
						AudioFormat.CHANNEL_IN_MONO,
						AudioFormat.ENCODING_PCM_16BIT);

				recorder = new AudioRecord(
						MediaRecorder.AudioSource.VOICE_COMMUNICATION,
						C.samplesPerSec, AudioFormat.CHANNEL_IN_MONO,
						AudioFormat.ENCODING_PCM_16BIT, bufSize);

				System.out.println("Recording starting ... ");
				recorder.startRecording();
				System.out.println("Recording started ... ");
				long expectTime = System.currentTimeMillis();
				while (true && !stop) {
					long waitTime = expectTime - System.currentTimeMillis();
					if (waitTime > 0) {
						try {
							Thread.sleep(waitTime);
						} catch (Exception e) {
						}
					}
					expectTime = System.currentTimeMillis() + 10;
					if (stop)
						break;
					;
					int len = recorder.read(buffer, bufP, buffer.length - bufP);
					if (stop)
						break;
					System.out.println("reading buffer ...bb " + len);
					if (len < 0)
						throw new RuntimeException(
								"Error happens, buffer read " + len);
					bufP += len;
					if (bufP < buffer.length) // has remaining
						continue;

					// buffer read full
					C.encPcm.clear();
					C.encPcm.put(buffer);
					len = C.enc();
					if (len < 0)
						throw new RuntimeException("unexpected encoded length "
								+ len);
					else {
						C.encStream.position(0).limit(len);
						streamListener.onStream(C.encStream);
					}
					bufP = 0;
					expectTime = System.currentTimeMillis();
				}

				return null;
			}
		});
	}

	public static void stopRecording() {
		UDPSpeaker.resume();
		stop = true;
		try {
			Thread.sleep(70);
		} catch (InterruptedException e1) {
			e1.printStackTrace();
		}
		streamListener = null;
		if (recordTask != null) {
			recordTask.cancel(true);
			recordTask = null;
		}
		if (recorder != null) {
			try {
				recorder.stop();
			} catch (Exception e) {
			}
			try {
				recorder.release();
			} catch (Exception e) {
			}
			recorder = null;
		}
		if (service != null) {
			service.shutdown();
		}
	}
}
